/**
 * @(#)CoordinadorBundleProperties.java Jan 31, 2007
 *
 * Copyright (c) 2005-2010 Psiqueware S.A. de C.V. All Rights Reserved.
 * This software is the proprietary information Psiqueware S.A. de C.V.
 * Use is subject to license terms.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * <br/>Usuario : AngelElectrico
 * <br/>Creaci&oacute;n: Jan 31, 2007 - 8:55:02 AM
 * <br/>
 * <br/>
 * <br/><t5>Cambios :</t5>
 * <br/><b>Fecha | Autor  |  Cambios</b>
 * <ul>
 * <li>Jan 31, 2007 | <a href = "mailto:AngelElectrico@PsiqueWare.com">Angel El&eacute;ctrico</a> | Creaci&oacute;n del Objeto.</li>
 *
 * </ul>
 */

package com.psiqueware.alheli.i18n.propertyBundles;

import com.psiqueware.alheli.exception.NullArgumentException;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;

/**
 * Administra los {@link ResourceBundle} del sistema para los diferentes contextos.
 * <br/>Paquete Original: com.psiqueware.basico.portlet
 * <br/>Nombre  Original: CoordinadorBundleProperties
 * <br/>Oprima para ver : <a href="CoordinadorBundleProperties.java.html"><i>C&oacute;digo Fuente</i> </a>
 *
 * @author <a href="mailto:AngelElectrico@PsiqueWare.com">Angel El&eacute;ctrico</a>
 * @version Revision: 1.1 Jan 31, 2007 8:55:02 AM
 * @noinspection ClassWithoutLogger, DuplicateStringLiteralInspection
 */
public class CoordinadorBundleProperties implements com.psiqueware.alheli.i18n.CoordinadorBundles
{

    /**
     * Mapa con las definiciones de los bundles.
     */
    private Map<String, List<String>> m_baseNames = new HashMap<String, List<String>>();

    /**
     * Constructor de CoordinadorBundleProperties.
     */
    public CoordinadorBundleProperties()
    {
    }

    /**
     * Agrega un {@link ResourceBundle} a la colecci&oacute;n coordinada.
     *
     * @param contexto en el que se definir&aacute; el Bundle.
     * @param baseName nombre base del bundle.
     */
    public void agregarResourceBundle(String contexto, String baseName)
    {
        if (null == contexto)
            throw new NullArgumentException("<error>El argumento 'contexto' no puede ser NULL.</error>");
        if (null == baseName)
            throw new NullArgumentException("<error>El argumento 'baseName' no puede ser NULL.</error>");


        List<String> bundles = m_baseNames.get(contexto);
        if (null == bundles)
        {
            bundles = new ArrayList<String>();
            m_baseNames.put(contexto, bundles);
        }

        if (!bundles.contains(baseName))
        {
            bundles.add(baseName);
        }
    }

    /**
     * Agrega un {@link ResourceBundle} a la colecci&oacute;n coordinada y lo devuelve.
     *
     * @param contexto en el que se definir&aacute; el Bundle.
     * @param baseName nombre base del bundle.
     *
     * @return {@link ResourceBundle} buscado.
     */
    public ResourceBundle agregaBuscaResourceBundle(String contexto, String baseName, Locale locale)
    {
        agregarResourceBundle(contexto, baseName);
        return getBundle(locale, contexto);
    }

    /**
     * Agrega un {@link ResourceBundle} a la colecci&oacute;n coordinada.
     *
     * @param contexto      en el que se definir&aacute; el Bundle.
     * @param classBaseName nombre base del bundle.
     */
    public void agregarResourceBundle(String contexto, Class classBaseName)
    {
        agregarResourceBundle(contexto, classBaseName.getName());
    }

    /**
     * Agrega un {@link ResourceBundle} a la colecci&oacute;n coordinada.
     *
     * @param baseName nombre base del bundle.
     */
    public void agregarResourceBundle(final String baseName)
    {
        agregarResourceBundle("", baseName);
    }

    /**
     * Agrega un {@link ResourceBundle} a la colecci&oacute;n coordinada.
     *
     * @param classBaseName nombre base del bundle.
     */
    public void agregarResourceBundle(final Class classBaseName)
    {
        agregarResourceBundle("", classBaseName);
    }

    /**
     * Agrega un {@link ResourceBundle} a la colecci&oacute;n coordinada y lo devuelve.
     *
     * @param contexto      en el que se definir&aacute; el Bundle.
     * @param classBaseName nombre base del bundle.
     *
     * @return {@link ResourceBundle} buscado.
     */
    public ResourceBundle agregaBuscaResourceBundle(String contexto, Class classBaseName, Locale locale)
    {
        return agregaBuscaResourceBundle(contexto, classBaseName.getName(), locale);
    }

    /**
     * Agrega un {@link ResourceBundle} a la colecci&oacute;n coordinada y lo devuelve.
     *
     * @param classBaseName nombre base del bundle.
     * @param locale        {@link Locale} del bundle buscado.
     *
     * @return {@link ResourceBundle} buscado.
     */
    public ResourceBundle agregaBuscaResourceBundle(final Class classBaseName, final Locale locale)
    {
        return agregaBuscaResourceBundle("", classBaseName, locale);
    }

    /**
     * Agrega un {@link ResourceBundle} a la colecci&oacute;n coordinada y lo devuelve.
     *
     * @param baseName nombre base del bundle.
     *
     * @return {@link ResourceBundle} buscado.
     */
    public ResourceBundle agregaBuscaResourceBundle(final String baseName)
    {
        return agregaBuscaResourceBundle("", baseName, Locale.getDefault());
    }

    /**
     * Agrega un {@link ResourceBundle} a la colecci&oacute;n coordinada y lo devuelve.
     *
     * @param classBaseName nombre base del bundle.
     *
     * @return {@link ResourceBundle} buscado.
     */
    public ResourceBundle agregaBuscaResourceBundle(final Class classBaseName)
    {
        return agregaBuscaResourceBundle("", classBaseName, Locale.getDefault());
    }


    /**
     * Devuelve un ResourceBundle para un {@link Locale} y contexto espec&iacute;ficos.
     *
     * @param locale   localidad cuyos recursos se buscan.
     * @param contexto para el Bundle.
     *
     * @return {@link ResourceBundle}.
     */
    public ResourceBundle getBundle(Locale locale, String contexto)
    {
        //validamos
        final List<String> baseNames = m_baseNames.get(contexto);
        if (null == baseNames)
            throw new NullArgumentException("<error><msg>El listado de 'baseNames' no puede ser NULL.</msg><parameters>" + contexto + "</parameters></error>");
        if (0 == baseNames.size())
            throw new IllegalArgumentException("<error>La lista de 'baseNames' no puede encontrarse vacio.</error>");

        BasicoResourceBundleCombinado salida = new BasicoResourceBundleCombinado(locale);
        for (String baseName : baseNames)
        {
            final ResourceBundle resourceBundle = ResourceBundle.getBundle(baseName, locale);
            salida.agregarRecursos(resourceBundle);
        }
        return salida;
    }

    /**
     * Devuelve un ResourceBundle para el {@link Locale} sin importarle el contexto de los recursos.
     *
     * @param locale localidad cuyos recursos se buscan.
     *
     * @return {@link ResourceBundle}.
     *
     * @noinspection MethodWithMultipleLoops
     */
    public ResourceBundle getBundle(Locale locale)
    {
        BasicoResourceBundleCombinado salida = new BasicoResourceBundleCombinado(locale);

        final Set<String> entries = m_baseNames.keySet();
        for (String contexto : entries)
        {
            //validamos
            final List<String> baseNames = m_baseNames.get(contexto);
            assert (null != baseNames) : ("<error><msg>El listado de 'baseNames' no puede ser NULL.</msg><parameters>" + contexto + "</parameters></error>");
            //agregamos
            for (String baseName : baseNames)
            {
                final ResourceBundle resourceBundle = ResourceBundle.getBundle(baseName, locale);
                salida.agregarRecursos(resourceBundle);
            }
        }
        return salida;
    }

    /**
     * Devuelve un ResourceBundle sin importarle el contexto de los recursos y utilizando el {@link Locale} por defecto.
     *
     * @return {@link ResourceBundle}.
     */
    public ResourceBundle getBundle()
    {
        return getBundle(Locale.getDefault(), "");
    }

    /**
     * Convierte este {@link CoordinadorBundleProperties} a su representaci&oacute;n textual.
     *
     * @noinspection DuplicateStringLiteralInspection, HardCodedStringLiteral, HardcodedLineSeparator
     */
    public String toString()
    {
        StringBuilder sb = new StringBuilder();
        sb.append("<Instance Class = '").append(this.getClass().getCanonicalName()).append("'>");
        sb.append("<baseNames>").append(m_baseNames).append("</baseNames> ");
        sb.append("</Instance>");
        return sb.toString();
    }
}

